import { defineEventHandler, setResponseHeader, getRequestURL } from 'h3'; import { createPageHandler } from '@beatzball/litro/runtime/create-page-handler.js'; import { DEFAULT_SKIP_LINKS } from '@beatzball/litro'; import type { LitroRoute } from '@beatzball/litro'; import { routes, pageModules } from '#litro/page-manifest'; function matchRoute( pathname: string, ): { route: LitroRoute; params: Record } | undefined { for (const route of routes) { if (route.isCatchAll) return { route, params: {} }; if (!route.isDynamic) { if (pathname === route.path) return { route, params: {} }; continue; } const regexStr = '^' + route.path .replace(/:([^/]+)\(\.\*\)\*/g, '(?<$1>.+)') .replace(/:([^/?]+)\?/g, '(?<$1>[^/]*)?') .replace(/:([^/]+)/g, '(?<$1>[^/]+)') + '$'; try { const match = pathname.match(new RegExp(regexStr)); if (match) return { route, params: (match.groups ?? {}) as Record }; } catch { // malformed pattern — skip } } return undefined; } export default defineEventHandler(async (event) => { const pathname = getRequestURL(event).pathname; const result = matchRoute(pathname); if (!result) { setResponseHeader(event, 'content-type', 'text/html; charset=utf-8'); return ` 404

404 — Not Found

No page matched ${pathname}.

`; } const { route: matched, params } = result; event.context.params = { ...event.context.params, ...params }; const mod = pageModules[matched.filePath]; const handler = createPageHandler({ route: matched, routeMeta: (mod?.routeMeta as { title?: string; head?: string } | undefined), pageModule: mod, skipLinks: [ ...DEFAULT_SKIP_LINKS, { label: 'Skip to navigation', href: '#_litro_nav' }, ], }); return handler(event); });